package com.turing.data.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.turing.common.util.StringUtils;
import com.turing.data.dao.review.ReviewedRecordsMapper;
import com.turing.data.model.domain.review.ReviewedRecords;
import com.turing.data.service.ResultStatisticService;
import com.turing.data.service.element.ElementService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ResultStatisticServiceImpl implements ResultStatisticService {

    private static final Log logger = LogFactory.getLog(ResultStatisticServiceImpl.class);

    @Autowired
    private ReviewedRecordsMapper reviewedRecordsMapper;

    @Autowired
    private ElementService elementService;


    public String calculateCorrectness(String templateSn, Integer eleId, String dateBegin, String dateEnd) {

        List<ReviewedRecords> reviewedRecords = getReviewedRecordsByCondition(templateSn, eleId, dateBegin, dateEnd);

        int total = 0;
        int correct = 0;

        Map<String, List<ReviewedRecords>> taskGroup = reviewedRecords.parallelStream()
                .collect(Collectors.groupingBy(ReviewedRecords::getParentTaskSn));

        for (String parentTaskSn : taskGroup.keySet()) {
            List<ReviewedRecords> taskRecords = taskGroup.get(parentTaskSn);

            Map<Integer, List<ReviewedRecords>> versionGroup = taskRecords.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getVersion));

            List<ReviewedRecords> firstVersion = versionGroup.get(-1);
            List<ReviewedRecords> lastVersion = versionGroup.get(0);

            Map<Integer, List<ReviewedRecords>> eleGroupFirst = firstVersion.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getEleId));

            Map<Integer, List<ReviewedRecords>> eleGroupLast = lastVersion.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getEleId));

            for (Integer ele : eleGroupLast.keySet()) {

                List<ReviewedRecords> reviewed = eleGroupLast.get(ele);

                List<ReviewedRecords> init = eleGroupFirst.get(ele);

                boolean empty = true;
                boolean match = false;

                for (ReviewedRecords record : reviewed) {
                    String businessValue = record.getBusinessValue();

                    if (!StringUtils.isEmpty(businessValue)) {
                        empty = false;

                        for (ReviewedRecords r : init) {
                            String bv = r.getBusinessValue();
                            if (!StringUtils.isEmpty(bv)) {
                                if (bv.equals(businessValue)) {
                                    match = true;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (!empty) {
                    total++;
                }
                if (match) {
                    correct++;
                }
            }

        }

        if (total == 0) {
            return "0";
        }
        DecimalFormat df = new DecimalFormat("0.##");
        return df.format((double) correct / (double) total) + "";
    }

    private List<ReviewedRecords> getReviewedRecordsByCondition(String templateSn, Integer eleId, String dateBegin, String dateEnd) {
        QueryWrapper<ReviewedRecords> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("isDel", 0);

        if (!StringUtils.isEmpty(templateSn)) {
            queryWrapper.eq("templateId", templateSn);
        }

        if (eleId != null) {
            queryWrapper.eq("id", eleId);
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (!StringUtils.isEmpty(dateBegin)) {
            try {
                Date begin = format.parse(dateBegin + " 00:00:00");
                queryWrapper.ge("taskUploadTime", begin);
            } catch (ParseException e) {
                logger.error("date begin parse error:" + dateBegin);
            }

        }

        if (!StringUtils.isEmpty(dateEnd)) {
            try {
                Date end = format.parse(dateEnd + " 23:59:59");
                queryWrapper.le("taskUploadTime", end);
            } catch (ParseException e) {
                logger.error("date end parse error:" + dateEnd);
            }
        }

        return reviewedRecordsMapper.selectList(queryWrapper);
    }


    @Override
    public String calculateCorrectnessByModelValue(String templateSn, Integer eleId, String dateBegin, String dateEnd) {

        List<ReviewedRecords> reviewedRecords = getReviewedRecordsByCondition(templateSn, eleId, dateBegin, dateEnd);

        int total = 0;
        int correct = 0;

        Map<String, List<ReviewedRecords>> taskGroup = reviewedRecords.parallelStream()
                .collect(Collectors.groupingBy(ReviewedRecords::getParentTaskSn));


        LinkedList<JSONObject> resList = new LinkedList<>();

        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("错误记录");
        XSSFRow firstRow = sheet.createRow(0);
        firstRow.createCell(0).setCellValue("parentTaskSn");
        firstRow.createCell(1).setCellValue("id");
        firstRow.createCell(2).setCellValue("原始值");
        firstRow.createCell(3).setCellValue("修改值");

        int i = 1;
        for (String parentTaskSn : taskGroup.keySet()) {
            List<ReviewedRecords> taskRecords = taskGroup.get(parentTaskSn);

            Map<Integer, List<ReviewedRecords>> versionGroup = taskRecords.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getVersion));

            List<ReviewedRecords> firstVersion = versionGroup.get(-1);
            List<ReviewedRecords> lastVersion = versionGroup.get(0);

            Map<Integer, List<ReviewedRecords>> eleGroupFirst = firstVersion.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getEleId));

            Map<Integer, List<ReviewedRecords>> eleGroupLast = lastVersion.parallelStream()
                    .collect(Collectors.groupingBy(ReviewedRecords::getEleId));

            for (Integer ele : eleGroupLast.keySet()) {

                List<ReviewedRecords> reviewed = eleGroupLast.get(ele);

                List<ReviewedRecords> init = eleGroupFirst.get(ele);

                boolean empty = true;
                boolean match = false;

                for (ReviewedRecords record : reviewed) {
//                    String businessValue = record.getBusinessValue();

                    String text = record.getText();
                    if (!StringUtils.isEmpty(text)) {
                        empty = false;

                        for (ReviewedRecords r : init) {
//                            String bv = r.getBusinessValue();
                            String rMV = r.getText();
                            if (!StringUtils.isEmpty(rMV)) {
                                if (rMV.equals(text)) {
                                    match = true;
                                    break;
                                }
                            }
                        }
                    }
                }

                if (!empty) {
                    total++;
                }
                if (match) {
                    correct++;
                }
                StringBuilder reviewedStr = new StringBuilder();
                reviewed = reviewed.parallelStream().sorted(Comparator.comparing(ReviewedRecords::getText)).collect(Collectors.toList());
                for (ReviewedRecords records : reviewed) {
                    reviewedStr.append(records.getText());
                }

                init = init.parallelStream().sorted(Comparator.comparing(ReviewedRecords::getText)).collect(Collectors.toList());
                StringBuilder initStr = new StringBuilder();
                for (ReviewedRecords records : init) {
                    initStr.append(records.getText());
                }

                if (!StringUtils.isEmpty(initStr.toString()) && !StringUtils.isEmpty(reviewedStr.toString())) {

                    if (!initStr.toString().equals(reviewedStr.toString())) {
                        XSSFRow row = sheet.createRow(i);
                        row.createCell(0).setCellValue(parentTaskSn);
                        row.createCell(1).setCellValue(elementService.getElementById(ele).getName());
                        row.createCell(2).setCellValue(initStr.toString());
                        row.createCell(3).setCellValue(reviewedStr.toString());

                        i++;
                    }

                } else {
                    correct--;
                    total--;
                }


            }

        }

        if (total == 0) {
            return "0";
        }
        DecimalFormat df = new DecimalFormat("0.##");
        return df.format((double) correct / (double) total) + "";
    }


    public static void main(String[] args) {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(RoundingMode.HALF_UP);
        System.out.println(df.format(2d / 3d));
    }
}
